using KinonekoSoftware.CodariaDB.Documents.Index;

namespace KinonekoSoftware.CodariaDB.Core
{
    /// <summary>
    /// <see cref="UsageSystem"/> 类型表示一个引用引擎，用来处理设定之间相互关联的情况。
    /// </summary>
    public sealed class UsageSystem : Engine
    {
        public void Add(Usage usage)
        {
            if (usage is null)
            {
                return;
            }

            InsideDB.Insert(usage);
            Modified();
        }

        public void Changed(Usage usage)
        {
            
        }
        
        public void Update(Usage usage)
        {
            if (usage is null)
            {
                return;
            }

            InsideDB.Update(usage);
        }
        
        public void Remove(Usage usage)
        {
            if (usage is null)
            {
                return;
            }

            InsideDB.Delete(usage.Id);
        }
        
        public void Remove(string sourceID, string targetID, InstanceType type)
        {
            if (string.IsNullOrEmpty(sourceID) || string.IsNullOrEmpty(targetID))
            {
                return;
            }

            var attachment = InsideDB.FindOne(x => x.Type == type && x.ReferenceSourceID == sourceID && x.ReferenceTargetID == targetID);

            //
            //
            if (attachment is null)
            {
                return;
            }
            
            //
            //
            InsideDB.Delete(attachment.Id);
        }

        public ISet<string> FindAbilityUsage(string id)
        {
            return InsideDB.Find(x => x.Type == InstanceType.Ability && x.ReferenceTargetID == id)
                                 .Select(x => x.ReferenceSourceID)
                                 .ToHashSet();
        }

        protected override void OnDatabaseOpening(RepositoryOpenContext context)
        {
            InsideDB = context.Repository.Get<Usage>(CollectionNames.AttachmentDB);
        }

        protected override void OnDatabaseClosing(ILogger logger)
        {
            InsideDB = null;
        }

        public ILiteCollection<Usage> InsideDB { get; private set; }

        public override string EngineID => EngineNames.Attachments;
    }

    public sealed class Usage : RootObject
    {
        public string       ReferenceSourceID { get; init; }
        public string       ReferenceTargetID { get; init; }
        public InstanceType Type              { get; init; }
        public int          ExtraTypeA        { get; init; }
        public string       ExtraTypeB        { get; init; }
    }
}